import * as THREE from 'three'
import { GUI } from 'lil-gui'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'

const gui = new GUI()
const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight)
camera.position.set(2, 2, 2)
scene.add(camera)

const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.outputColorSpace = THREE.SRGBColorSpace

renderer.useLegacyLights = true

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

document.body.appendChild(renderer.domElement)

const axHelp = new THREE.AxesHelper(5)
scene.add(axHelp)

const cube = new THREE.Mesh(
  new THREE.SphereGeometry(0.6, 32, 32),
  new THREE.MeshStandardMaterial({ color: '#fff' })
)
cube.castShadow = true
scene.add(cube)

const plane = new THREE.Mesh(
  new THREE.PlaneGeometry(10, 10),
  new THREE.MeshStandardMaterial({ color: '#f2f2f2' })
)
plane.rotation.x = -Math.PI / 2
plane.position.y = -1
plane.receiveShadow = true
scene.add(plane)

const light = new THREE.AmbientLight('#fff', 0.5)
scene.add(light)

const light1 = new THREE.RectAreaLight('purple', 16, 2, 2)
light1.position.set(-1, 1, 1)
light1.lookAt(new THREE.Vector3())
scene.add(light1)

const light1Help = new RectAreaLightHelper(light1)
scene.add(light1Help)

const light2 = new THREE.SpotLight('#78ff00', 5, 8, Math.PI / 10, 0.5, 1)
light2.position.set(0, 3, 3)
light2.castShadow = true
light2.shadow.mapSize.set(1024, 1024)
scene.add(light2)

light2.target.position.x = 1

const light2Help = new THREE.SpotLightHelper(light2)
scene.add(light2Help)

gui.add(light2, 'angle').min(0).max(Math.PI / 2).step(0.1).onChange(() => {
  light2Help.update()
})
gui.add(light2, 'decay').min(0).max(1).step(0.1).onChange(() => {
  light2Help.update()
})

gui.add(light2.target.position, 'x').min(-4).max(4).step(0.1).onChange(() => {
  light2Help.update()
})

gui.add(light2, 'distance').min(1).max(10).step(0.1).onChange(() => {
  light2Help.update()
})

const handleRender = () => {
  controls.update()
  renderer.render(scene, camera)
  window.requestAnimationFrame(handleRender)
}

const handleSize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()

  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
}

window.addEventListener('resize', handleSize)

handleRender()
